package com.yule.filter;

import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.yule.util.MD5Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

/**
 * @author gjl
 * @description 2017/8/31
 */
@Component
public class SysFilter extends ZuulFilter {

    private static Logger logger = LoggerFactory.getLogger(SysFilter.class);

    private JSONObject rs = null;

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        rs = new JSONObject();

        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        HttpServletResponse response = ctx.getResponse();
        PrintWriter out = null;
        StringBuffer sbUrl = request.getRequestURL();
        String url = sbUrl.toString();
        //logger.info("路由选择器请求路径：" + url);
        String json = request.getParameter("json");

        ApplicationContext applicationContext = WebApplicationContextUtils
                .getWebApplicationContext(request.getServletContext());
        StringRedisTemplate srt = (StringRedisTemplate) applicationContext.getBean("stringRedisTemplate");

        try {
            response.setContentType("text/html;charset=utf-8");
            //out = response.getWriter();
            if (json == null || json.length() < 1) {
                ctx.setSendZuulResponse(false);
                logger.info("无参数传递");
                rs.put("msg", "无参数传递");
                rs.put("success", "0");
                ctx.setResponseBody(rs.toJSONString());
                return null;
            }

            JSONObject jObject = JSONObject.parseObject(json);
            Set<Entry<String, Object>> set = jObject.entrySet();
            Map<String, Object> sortMap = new TreeMap<String, Object>();
            for (Entry<String, Object> entry : set) {
                sortMap.put(entry.getKey(), entry.getValue());
            }
            Set<?> es = sortMap.entrySet();
            Iterator<?> it = es.iterator();

            String key = "";
            String method = "";
            String pubSign = "";
            String paramNames = "";
            String v = "";
            String k = "";
            String timeStamp = "";
            StringBuffer sb = new StringBuffer();

            while (it.hasNext()) {
                Entry entry = (Entry) it.next();
                k = entry.getKey().toString();
                if (k.equals("sign")) {
                    pubSign = entry.getValue().toString();
                } else if (k.equals("timestamp")) {
                    timeStamp = entry.getValue().toString();
                } else if (k.equals("key")) {
                    key = entry.getValue().toString();
                } else if (k.equals("method")) {
                    method = entry.getValue().toString();
                } else {
                    paramNames += k;
                    v = entry.getValue().toString();
                    sb.append(k + "=" + v.trim() + "&");
                    //CQ.put(k, v);
                }
            }

            String redisSid = srt.opsForValue().get("saleStationId_" + key);
            if (redisSid == null) {
                ctx.setSendZuulResponse(false);
                logger.info("零售商ID不正确");
                rs.put("msg", "零售商ID不正确");
                rs.put("success", "0");
                ctx.setResponseBody(rs.toJSONString());
                return null;
            }

            String redisMethod = srt.opsForValue().get("requestUrl_" + method);
            if (redisMethod == null) {
                ctx.setSendZuulResponse(false);
                logger.info("无对应的请求路径");
                rs.put("msg", "无对应的请求路径");
                rs.put("success", "0");
                ctx.setResponseBody(rs.toJSONString());
                return null;
            }

            if (timeStamp == null || timeStamp.length() < 1) {
                ctx.setSendZuulResponse(false);
                logger.info("时间戳不能为空");
                rs.put("msg", "时间戳不能为空");
                rs.put("success", "0");
                ctx.setResponseBody(rs.toJSONString());
                return null;
            }

            long nowTimeStamp = System.currentTimeMillis();
            long ts = Long.parseLong(timeStamp);
            if (((nowTimeStamp - ts) / 1000) > 30000) {
                ctx.setSendZuulResponse(false);
                logger.info("请求时间已超时，请重新定义时间戳");
                rs.put("msg", "请求时间已超时，请重新定义时间戳");
                rs.put("success", "0");
                ctx.setResponseBody(rs.toJSONString());
                return null;
            }

            String redisMethodPara = srt.opsForValue().get("requestPara_" + method);
            if (!redisMethodPara.equals(paramNames)) {
                ctx.setSendZuulResponse(false);
                logger.info("请求参数不正确");
                rs.put("msg", "请求参数不正确");
                rs.put("success", "0");
                ctx.setResponseBody(rs.toJSONString());
                return null;
            }

            String string = sb.toString().substring(0, sb.toString().length() - 1);
            string += "&timestamp=" + timeStamp;
            if (string.contains("=&")) {
                ctx.setSendZuulResponse(false);
                logger.info("参数不能为空");
                rs.put("msg", "参数不能为空");
                rs.put("success", "0");
                ctx.setResponseBody(rs.toJSONString());
                return null;
            }

            if (!pubSign.equals(MD5Util.getMD5(string))) {
                ctx.setSendZuulResponse(false);
                logger.info("报文对比错误");
                rs.put("msg", "报文对比错误");
                rs.put("success", "0");
                ctx.setResponseBody(rs.toJSONString());
                return null;
            }
            ctx.setSendZuulResponse(true);
            logger.info("正确请求，参数为：" + json);
            return null;
        } catch (Exception e) {
            ctx.setSendZuulResponse(false);
            logger.info(e.getMessage());
            rs.put("msg", "请求错误");
            rs.put("success", "0");
            out.write(rs.toJSONString());
            out.close();
            return null;
        }
    }
}
